#include "stdafx.h"

#include "viewport.h"

#include <boost/foreach.hpp>

CViewport::CViewport(const SRect & rct) : _rct(rct), _viewportMode(VP3D), _matrixMode(GL_MODELVIEW), _idx(0){}

void CViewport::resize(int w, int h)
{	
	_rct.w = w;
	_rct.h = (h == 0) ? 1 : h;

	std::pair<unsigned int, int(*)(const SRect &)> p;

	BOOST_FOREACH(p, _listeners)
	{
		p.second(_rct);
	}

	activate();
}

void CViewport::activate() const
{
	glViewport(0, 0, _rct.w, _rct.h);
	resetMode();
}

void CViewport::resetMode() const
{
	switch (_viewportMode)
	{
	case VP2D:
		switchTo2DMode();
		break;
	case VP3D:
		switchTo3DMode();
		break;
	default:
		break;
	}
}

void CViewport::switchTo2DMode() const
{
	_matrixMode = GL_MODELVIEW;
	_viewportMode = VP2D;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0.0, (GLfloat)_rct.w, 0.0, (GLfloat)_rct.h, -1.0, 1.0); 
	glMatrixMode(GL_MODELVIEW);

}

void CViewport::switchTo3DMode() const
{
	_matrixMode = GL_MODELVIEW;
	_viewportMode = VP3D;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(50.0f, (GLfloat)_rct.w / (GLfloat)_rct.h, 0.5f ,150000.0f);
	glMatrixMode(GL_MODELVIEW);

}

void CViewport::setMatrixMode(GLenum matrix_mode) const
{
	_matrixMode = matrix_mode;
	glMatrixMode(matrix_mode);
}

unsigned int CViewport::attach(int (*cbk)(const SRect & rect))
{
	_listeners[++_idx] = cbk;
	return _idx;
}

void CViewport::detach(unsigned int id)
{
	_listeners.erase(id);
}
